package com.jack.lib.ui.widget

import com.jack.lib.core.ext.MM
import kotlin.jvm.JvmOverloads
import android.animation.ValueAnimator
import androidx.annotation.IntDef
import android.view.animation.LinearInterpolator
import android.animation.ValueAnimator.AnimatorUpdateListener
import android.content.Context
import androidx.annotation.DrawableRes
import android.graphics.drawable.BitmapDrawable
import android.content.res.TypedArray
import android.graphics.*
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import com.jack.lib.ui.R

/**
 * 作者: jack(黄冲)
 * 邮箱: 907755845@qq.com
 * create on 2017/9/3 17:27
 */
class MoreStyleImageView @JvmOverloads constructor(
    context: Context, attrs:
    AttributeSet? = null,
    defStyleAttr: Int = 0) :
    JImageView(context, attrs, defStyleAttr) {

    private var mRotationTime = 20 * 1000
    private var mImageStyle: Int
    private var mRadii: Float
    private var mPaint: Paint? = null
    private var mValueAnimator: ValueAnimator? = null
    private var mAngle = 0f
    private val mPath = Path()
    private var mBitmap: Bitmap? = null
    private val mPadding: Int

    @IntDef(STYLE_CIRCLE, STYLE_SEMIROUNDED_RECTANGLE, STYLE_ROUNDED_RECTANGLE)
    annotation class ImageStyle

    init {
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.MoreStyleImageView)
        mImageStyle = typedArray.getInt(R.styleable.MoreStyleImageView_JStyle, STYLE_CIRCLE)
        mPadding =
            typedArray.getDimension(R.styleable.MoreStyleImageView_JSrcPadding, 0f).MM.toInt()
        mRadii = typedArray.getDimension(R.styleable.MoreStyleImageView_JRadian, 20f).MM
        val isAnimate = typedArray.getBoolean(R.styleable.MoreStyleImageView_JAnimate, false)
        typedArray.recycle()
        init()
        setRotationEnable(isAnimate)
    }


    private fun init() {
        mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
        mPaint!!.style = Paint.Style.FILL_AND_STROKE
        mPaint!!.isDither = true
        initAnimator()
    }

    /**
     * 设置图片显示的样式
     * @param imageStyle
     */
    fun setImageStyle(@ImageStyle imageStyle: Int) {
        mImageStyle = imageStyle
        invalidate()
    }

    /**
     * 设置圆角的弧度
     * @param radii
     */
    fun setRadii(radii: Int) {
        mRadii = radii.toFloat()
    }

    fun setRotationEnable(enable: Boolean) {
        setRotationEnable(enable, true)
    }

    fun setRotationEnable(enable: Boolean, isHome: Boolean) {
        if (enable) {
            mAngle = 0f
            mValueAnimator!!.start()
        } else {
            mAngle = if (isHome) 0F else mAngle
            mValueAnimator!!.cancel()
        }
    }

    /**
     * 默认旋转周期为20秒一次
     * @param time
     */
    fun setRotationTime(time: Int) {
        mRotationTime = time
    }

    private fun initAnimator() {
        mValueAnimator = ValueAnimator.ofFloat(0f, 1f).also {
            it.duration = mRotationTime.toLong()
            it.repeatMode = ValueAnimator.RESTART
            it.repeatCount = ValueAnimator.INFINITE
            it.interpolator = LinearInterpolator()
            it.addUpdateListener(mAnimatorUpdateListener)
        }
    }

    private val mAnimatorUpdateListener = AnimatorUpdateListener { valueAnimator ->
        mAngle = valueAnimator.animatedValue as Float
        postInvalidateOnAnimation()
    }

    override fun setImageBitmap(bm: Bitmap) {
        mBitmap = null
        super.setImageBitmap(bm)
    }

    override fun setImageResource(@DrawableRes resId: Int) {
        mBitmap = null
        super.setImageResource(resId)
    }

    override fun setImageDrawable(drawable: Drawable?) {
        mBitmap = null
        super.setImageDrawable(drawable)
    }

    override fun onDraw(canvas: Canvas) {
        if (drawable == null) return
        if (mBitmap == null && drawable is BitmapDrawable) {
            val bitmap = (drawable as BitmapDrawable).bitmap ?: return
            mBitmap = getBitmap(bitmap)
        }
        if (mBitmap != null) {
            canvas.rotate(mAngle * 360, (width / 2).toFloat(), (height / 2).toFloat())
            canvas.drawBitmap(mBitmap!!, 0f, 0f, mPaint)
        } else {
            canvas.save()
            canvas.clipPath(clipPath)
            super.onDraw(canvas)
            canvas.restore()
        }
    }

    private fun getBitmap(bitmap: Bitmap): Bitmap {
        initPaint()
        mRadii = if (mRadii < 0) 0F else mRadii
        val output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(output)
        val rectSrc = Rect(0, 0, bitmap.width, bitmap.height)
        val rectDest = Rect(0, 0, width, height)
        canvas.drawARGB(0, 0, 0, 0)
        if (mImageStyle == STYLE_CIRCLE) drawCircleBitmap(canvas)
        if (mImageStyle == STYLE_SEMIROUNDED_RECTANGLE) drawSemiroundedRectangleBitmap(canvas)
        if (mImageStyle == STYLE_ROUNDED_RECTANGLE) drawRoundedCornersBitmap(canvas)
        mPaint!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(bitmap, rectSrc, rectDest, mPaint)
        mPaint!!.xfermode = null
        return output
    }

    private fun initPaint() {
        mPaint!!.style = Paint.Style.FILL
        mPaint!!.color = Color.WHITE
        mPaint!!.strokeWidth = 1f
    }

    /**
     * 绘制圆形图片
     * @return Bitmap
     * @author caizhiming
     */
    private fun drawCircleBitmap(canvas: Canvas) {
        canvas.drawCircle(
            (width / 2).toFloat(),
            (height / 2).toFloat(),
            (width / 2 - mPadding).toFloat(),
            mPaint!!
        )
    }

    /**
     * 绘制半圆角的图片
     * @return
     */
    private fun drawSemiroundedRectangleBitmap(canvas: Canvas) {
        val path = Path()
        path.moveTo(0f, height.toFloat())
        path.lineTo(0f, mRadii)
        path.quadTo(0f, 0f, mRadii, 0f)
        path.lineTo(width - mRadii, 0f)
        path.quadTo(width.toFloat(), 0f, width.toFloat(), mRadii)
        path.lineTo(width.toFloat(), height.toFloat())
        path.close()
        canvas.drawPath(path, mPaint!!)
    }

    /**
     * 绘制圆角的图片
     * @return
     */
    private fun drawRoundedCornersBitmap(canvas: Canvas) {
        val rectF = RectF(0F, 0F, width.toFloat(), height.toFloat())
        canvas.drawRoundRect(rectF, mRadii, mRadii, mPaint!!)
    }

    private val clipPath: Path
        private get() {
            mPath.reset()
            when (mImageStyle) {
                STYLE_CIRCLE -> mPath.addCircle(
                    (width / 2).toFloat(),
                    (height / 2).toFloat(),
                    (width / 2 - mPadding).toFloat(),
                    Path.Direction.CW
                )
                STYLE_SEMIROUNDED_RECTANGLE -> {
                    mPath.moveTo(0f, height.toFloat())
                    mPath.lineTo(0f, mRadii)
                    mPath.quadTo(0f, 0f, mRadii, 0f)
                    mPath.lineTo(width - mRadii, 0f)
                    mPath.quadTo(width.toFloat(), 0f, width.toFloat(), mRadii)
                    mPath.lineTo(width.toFloat(), height.toFloat())
                    mPath.close()
                }
                STYLE_ROUNDED_RECTANGLE -> mPath.addRoundRect(
                    0f,
                    0f,
                    width.toFloat(),
                    height.toFloat(),
                    mRadii,
                    mRadii,
                    Path.Direction.CW
                )
            }
            return mPath
        }

    companion object {
        /**
         * 圆形样式
         */
        const val STYLE_CIRCLE = 1

        /**
         * 顶部两个圆角
         */
        const val STYLE_SEMIROUNDED_RECTANGLE = 2

        /**
         * 四周圆角
         */
        const val STYLE_ROUNDED_RECTANGLE = 3
    }

}